跳到主要内容

JavaScript WebWorkers多线程

什么是 Web Workers?

Web Workers 是 HTML5 提供的一个 JavaScript 多线程的解决方案,但是子线程完全受主线程控制,且不得操作 DOM;所以,这个新标准并没有改变 JavaScript 单线程的本质,UI 界面只能由主线程来操作

这个 Web Workers 常用于计算(CPU 密集型的操作)

通过使用 Web Workers,We b应用程序可以在独立于主线程的后台线程中,运行一个脚本操作。这样做的好处是可以在独立线程中执行费时的处理任务,从而允许主线程(通常是UI线程)不会因此被阻塞/放慢。

举个阻塞的例子(这次高级一点,用斐波那契数列)

<!-- placeholder属性是用来显示输入框提示内容的 -->
<input id='number' type="number" placeholder="数值">
<!-- 计算結果 斐波那契数列 -->
<button>计算</button>
// 后一个数是前两个数的和
// 1 1 2 3 5 8 f(n) = f(n-1) + f(n-2)
function fibonacci(n) {
return n <= 2 ? 1 : fibonacci(n - 1) + fibonacci(n - 2)
}

$('button').click(() => {
console.log($('#number').val());
console.log(fibonacci($('#number').val()));
})

输入的值从 40 开始就要算很久了,主要是递归效率比较低

如何使用 Web Workers

<!-- placeholder属性是用来显示输入框提示内容的 -->
<input id='number' type="number" placeholder="数值">
<!-- 计算搜尋結果 斐波那契数列 -->
<button id="count">计算</button>
<button>用来测试页面是否阻塞</button>

Worker 接口的 onmessage 属性表示一个 EventHandler 事件处理函数,当 message 事件发生时,该函数被调用。

主线程的

$('#count').click(() => {
let number = $('#number').val()

// 创建一个worker对象 传入的参数是一个脚本地址
const worker = new Worker('./temp.js')
// 向分线程发送消息
worker.postMessage(number)
console.log('主线程向分线程发送了数据');

// 主线程通过 worker.onmessage 指定监听函数
// 注册一个监听,用来接收worker传过来的数据函数,就是当监听的事件发生时自动执行这个回调函数
worker.onmessage = function (event) {
// 返回来的数据通过event.data拿到
console.log('主线程收到来自分线程的数据:' + event.data);
}
})

请注意,主线程中必须以 myWorker.onmessage 方式调用, 反之 worker.js 脚本中, 只需定义 onmessage,因为 worker.js 全域有效(具体参考 DedicatedWorkerGlobalScope

Worker 接口的 postMessage() 方法 向 worker 的内部作用域发送一个消息(具体参考 postMessage 函数

子线程的

// 后一个数是前两个数的和
// 1 1 2 3 5 8 f(n) = f(n-1) + f(n-2)
function fibonacci(n) {
return n <= 2 ? 1 : fibonacci(n - 1) + fibonacci(n - 2)
}

// 主线程中必须以myWorker.onmessage方式调用, 反之worker.js 脚本中, 只需定义 onmessage, 因为worker.js全域有效
onmessage = function (event) {
console.log('分线程收到来自主线程发送来的数据' + event.data);
// 开始计算
let num = fibonacci(event.data)
postMessage(num)
console.log('分线程已向主线程返回数据');
}

References